#include "wtlpch.h"

#include "resource.h"
#include "ItemsCheckDiag.h"
#include "TARegisterHelper.h"

#define SELECTED_INFO_BUFFER_SIZE		64

//The two status of listview was not found in the Win32API So we define it ourself
#ifndef LVIS_UNCHECKED
#define LVIS_UNCHECKED		0x1000
#endif

#ifndef LVIS_CHECKED
#define LVIS_CHECKED		0x2000
#endif


CItemsCheckDiag::CItemsCheckDiag() : m_uiCheckedItems(0), m_fCheckeFileSize(0.0f), m_pwstrInfoFormat(NULL), m_pwstrInfoBuffer(NULL)
{
	//Allocate the infowindow string, cause we use it many times
	m_pwstrInfoFormat = new WCHAR[SELECTED_INFO_BUFFER_SIZE];	::wmemset(m_pwstrInfoFormat, 0, SELECTED_INFO_BUFFER_SIZE);
	m_pwstrInfoBuffer = new WCHAR[SELECTED_INFO_BUFFER_SIZE];	::wmemset(m_pwstrInfoBuffer, 0, SELECTED_INFO_BUFFER_SIZE);

	::LoadStringW(::GetModuleHandle(NULL), IDS_TA_SELECTED_ITEM_FORMAT, m_pwstrInfoFormat, SELECTED_INFO_BUFFER_SIZE);
}

CItemsCheckDiag::~CItemsCheckDiag()
{
	//Release buffer
	if(m_pwstrInfoFormat != NULL)
	{
		delete m_pwstrInfoFormat;
	}

	if(m_pwstrInfoBuffer != NULL)
	{
		delete m_pwstrInfoBuffer;
	}
}

LRESULT CItemsCheckDiag::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
	// center the dialog on for the parent
	CenterWindow(GetParent());

	//Attach static info
	m_stcSelectedInfo.Attach(GetDlgItem(IDC_STATIC_ITEMS_SELECTED));
	m_stcSelectedInfo.SetWindowTextW(L"");

	//Subclassing List
	m_lstItemsList.SubclassWindow(GetDlgItem(IDC_ITEMS_LIST));
	m_lstItemsList.SetExtendedListViewStyle(m_lstItemsList.GetExtendedListViewStyle() | LVS_EX_GRIDLINES);

	//Add List item header
	m_lstItemsList.AddFileItemHeader();

	//Create Imagelist from item list, we created items list before show the diag
	//Then set the image list for the item list
	CreateItemIconList();
	m_lstItemsList.SetImageList(m_imglstFileTypeIcon, LVSIL_SMALL);

	//Add Listitems to list
	AddItemsToList();

	//Check All Items On Init if needed
	if(_ConfigApp.AppSettings.bIsInitSelectAll)
	{
		m_lstItemsList.SetAllItemsChecked();
	}
	
	//Neccessary for Resize
	DlgResize_Init();

	return TRUE;
}

LRESULT CItemsCheckDiag::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
	return FALSE;
}

LRESULT CItemsCheckDiag::OnOK(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
	//We found out the checkded items
	for(UINT i = 0; i< m_vecItemList.size(); i++)
	{
		if(m_lstItemsList.GetCheckState(i))
		{
			m_vecSelectedItemList.push_back(m_vecItemList[i]);
		}
	}

	CloseDialog(wID);
	return FALSE;
}

LRESULT CItemsCheckDiag::OnCancel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
	CloseDialog(wID);
	return FALSE;
}

void CItemsCheckDiag::CloseDialog(int nVal)
{
	EndDialog(nVal);
}

LRESULT CItemsCheckDiag::OnCheckItem(int idCtrl, LPNMHDR lpmhr, BOOL& bHandled)
{
	LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lpmhr;
	bool bIsChanged = false;

	//We Only pay attention on state change
	if(pnmv->uChanged == LVIF_STATE)
	{
		//From uncheck to checked
		if((pnmv->uOldState & LVIS_UNCHECKED) && (pnmv->uNewState & LVIS_CHECKED))
		{
			//Set Flag
			bIsChanged = true;

			//Increate the checked count
			m_uiCheckedItems++;
			//Increate file size count
			//CAUTION! This kind of iItem and vector usage is dangerous, but in this app
			//We do not rerange the items, so their iItem index are identical to their vecotr index
			//Do't do this kind of job in a rearangeable env
			m_fCheckeFileSize += m_vecItemList[pnmv->iItem].fFileMBSize;
		}
		else if((pnmv->uOldState & LVIS_CHECKED) && (pnmv->uNewState & LVIS_UNCHECKED))
		{
			//Set Flag
			bIsChanged = true;

			//From checked to unchecked
			//Decrease the cheked count
			m_uiCheckedItems--;
			//Decrease file size count, Reset float value for precision
			m_fCheckeFileSize = (m_uiCheckedItems == 0 ? 0.0f : m_fCheckeFileSize - m_vecItemList[pnmv->iItem].fFileMBSize);
		}
	}

	//To avoid too much redraw of info window
	if(bIsChanged)
	{
		::wmemset(m_pwstrInfoBuffer, 0, SELECTED_INFO_BUFFER_SIZE);
		::swprintf(m_pwstrInfoBuffer, SELECTED_INFO_BUFFER_SIZE, m_pwstrInfoFormat, m_uiCheckedItems, m_fCheckeFileSize);
		m_stcSelectedInfo.SetWindowTextW(m_pwstrInfoBuffer);
	}

	//We check the total status, and set the selall checkbox
	if(m_uiCheckedItems == m_vecItemList.size())
	{
		m_lstItemsList.m_ckCheckItemAll.SetCheck(BST_CHECKED);
	}
	else
	{
		m_lstItemsList.m_ckCheckItemAll.SetCheck(BST_UNCHECKED);
	}

	bHandled = FALSE;
	return FALSE;
}


void CItemsCheckDiag::CreateItemsList(map<string, vector<CHttpStreamHandler::JSItem>>& pmapItems, map<string, string>& mapSecIps)
{
	//Create a map to prevent dunplicate items
	map<wstring, CBoolWrapper> mapCheckExist;

	for(map<string, vector<CHttpStreamHandler::JSItem>>::iterator it = pmapItems.begin(); it != pmapItems.end(); ++it)
	{
		string strRef = (*it).first;

		//Read the JSItem to create item
		for(vector<CHttpStreamHandler::JSItem>::iterator iti = (*it).second.begin(); iti != (*it).second.end(); ++iti)
		{
			CHttpStreamHandler::JSItem curJSItem = (*iti);
			CItemsCheckList::ITEM_LIST_DATA itemData;

			//We save the same file id before, so we supress this time
			if(mapCheckExist[curJSItem.wstrID].m_bool)
			{
				continue;
			}

			//We found a new one
			mapCheckExist[curJSItem.wstrID].m_bool = true;

			//Save the referer
			itemData.strURLRefer = strRef;

			//Save the SecIp
			itemData.strSecIP = mapSecIps[strRef];

			//Save the fileID
			itemData.wstrFileID = curJSItem.wstrID;

			//Convert kb size to mb, if no size data, we supress the size data
			itemData.fFileMBSize = (FLOAT)curJSItem.uiFileSizeKB / 1024;
			if(itemData.fFileMBSize != 0.0f)
			{
				//10 Digitals is OK
				WCHAR pMBSize[10] = { 0 };
				::swprintf(pMBSize, 10, L"%.2f M", itemData.fFileMBSize);
				itemData.wstrFileMBSize = pMBSize;
			}

			//Save the filename
			itemData.wstrFileName = curJSItem.wstrFileName;

			//Push the item to the vector
			m_vecItemList.push_back(itemData);
		}
	}
}

void CItemsCheckDiag::CreateItemIconList()
{
	//Create the image list, we known the size exactly, and cause of icon file
	//So we assume it to be 32bit kind, I really do not known the ILC_MASK effects
	//But add this will give transparent bk, so I added that
	ATLASSERT(m_vecItemList.size() != 0);
	m_imglstFileTypeIcon.Create(16, 16, ILC_COLOR32 | ILC_MASK, m_vecItemList.size(), 0);

	//iterate the item map, and set item list
	for(vector<CItemsCheckList::ITEM_LIST_DATA>::iterator it = m_vecItemList.begin(); it != m_vecItemList.end(); ++it)
	{
		m_imglstFileTypeIcon.AddIcon(CTARegisterHelper::RegGetIconFromExtension(CTARegisterHelper::ExtractExtFromFileName((*it).wstrFileName)));
	}
}

void CItemsCheckDiag::AddItemsToList()
{
	UINT uiItemCount = 0;

	//iterate the item map, and add it to list
	for(vector<CItemsCheckList::ITEM_LIST_DATA>::iterator it = m_vecItemList.begin(); it != m_vecItemList.end(); ++it, uiItemCount++)
	{
		m_lstItemsList.AddDownFileItem(uiItemCount, (*it));
	}	
}